package com.yk.common.core.utils;

import cn.dev33.satoken.config.SaSignConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yk.common.core.constant.UserConstants;
import com.yk.common.core.domain.LoginUser;
import com.yk.common.core.enums.DeviceType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 登录鉴权助手
 *
 * @author lmx
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LoginHelper {

    public static final String LOGIN_USER_KEY = "loginUser";
    public static final long DEFAULT_TIMEOUT = 259200L;

    /**
     * 会话登录 普通登录，这里重置下过期时间。
     *
     * @param loginUser loginUser
     */
    public static void login(LoginUser loginUser) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        StpUtil.login(loginUser.getUserId(), new SaLoginModel().setTimeout(DEFAULT_TIMEOUT));
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * 登录系统 基于 设备类型
     * 针对相同用户体系不同设备
     *
     * @param loginUser 登录用户信息
     */
    public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        SaLoginModel model = new SaLoginModel();
        model.setTimeout(DEFAULT_TIMEOUT);
        if (ObjectUtil.isNotNull(deviceType)) {
            model.setDevice(deviceType.getDevice());
        }
        StpUtil.login(loginUser.getUserId(), model);
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * 会话登录（记住我模式） 配置文件过期时间仅记住我模式使用，为了兼容TokenSession不为空的情况
     *
     * @param loginUser loginUser
     */
    public static void login2TimeOut(LoginUser loginUser) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        StpUtil.login(loginUser.getUserId(), new SaLoginModel().setIsLastingCookie(true));
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * 会话登录（记住我模式） 配置文件过期时间仅记住我模式使用，为了兼容TokenSession不为空的情况
     *
     * @param loginUser loginUser
     */
    public static void login2TimeOutByDevice(LoginUser loginUser, DeviceType deviceType) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        SaLoginModel model = new SaLoginModel();
        model.setIsLastingCookie(true);
        if (ObjectUtil.isNotNull(deviceType)) {
            model.setDevice(deviceType.getDevice());
        }
        StpUtil.login(loginUser.getUserId(), model);
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * 获取登录用户的信息
     *
     * @return 用户信息
     */
    public static LoginUser getLoginUser() {
        LoginUser loginUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY);
        if (loginUser != null) {
            return loginUser;
        }
        loginUser = (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        return loginUser;
    }

    /**
     * 获取登录用户的userId
     *
     * @return 用户ID
     */
    public static Long getLoginUserId() {
        LoginUser loginUser = getLoginUser();
        if (ObjectUtil.isNull(loginUser)) {
            return StpUtil.getLoginIdAsLong();
        }
        return loginUser.getUserId();
    }

    /**
     * 获取用户基于token
     *
     * @param token token
     * @return
     */
    public static LoginUser getLoginUser(String token) {
        SaSession session = StpUtil.getTokenSessionByToken(token);
        if (ObjectUtil.isNull(session)) {
            return null;
        }
        return (LoginUser) session.get(LOGIN_USER_KEY);
    }

    /**
     * 获取用户账户
     *
     * @return 账户名
     */
    public static String getUsername() {
        return getLoginUser().getUsername();
    }

    /**
     * 是否为管理员
     *
     * @param userId 用户ID
     * @return 结果
     */
    public static boolean isAdmin(Long userId) {
        return UserConstants.ADMIN_ID.equals(userId);
    }

    /**
     * 当前用户是否为管理员
     *
     * @return 结果
     */
    public static boolean isAdmin() {
        return isAdmin(getLoginUserId());
    }

    /**
     * 检验当前用户是否登录
     *
     * @return 已登录返回 false，未登录返回 true
     */
    public static boolean loginInd() {
        return !StpUtil.isLogin();
    }

    /**
     * 修改loginUser信息
     */
    public static void setLoginUser(LoginUser loginUser) {
        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
    }

    /**
     * api接口签名校验
     */
    public static void checkSign(String secretKey) {
        SaRequest request = SaHolder.getRequest();
        SaSignTemplate saSignTemplate = new SaSignTemplate();
        SaSignConfig config = new SaSignConfig();
        config.setSecretKey(secretKey);
        saSignTemplate.setSignConfig(config);
        saSignTemplate.checkParamMap(request.getParamMap());
    }
}
